#include "CalculateFeaturePoints.h"
#include <cmath>

namespace Graphics
{

	CalculateFeaturePoints::CalculateFeaturePoints(QPoint from, QPoint to)
		: _from(from)
		, _to(to)
	{

	}

	CalculateFeaturePoints::~CalculateFeaturePoints()
	{

	}

	LineType CalculateFeaturePoints::lineType()
	{
		int disX = _to.x() - _from.x();
		if (disX > 0)
		{
			if (disX > _turningPointLength * 2)
				return Line_ZTurning_Type;
			else if (disX > _arrowSize.width() * 4)
				return Line_ZCenter_Type;
		}
		int disY = fabs(_to.y() - _from.y());
		if (disY > _itemBottomHeight + _itemTopHeight + _turningPointLength * 2)
			return Line_STurning_Type;
		else if (disY > _itemBottomHeight + _itemTopHeight + _arrowSize.height() * 2)
			return Line_SCenter_Type;
		else
			return Line_OClock_Type;
	}

	QList<QPoint> CalculateFeaturePoints::featurePoints()
	{
		_lineType = lineType();
		switch (_lineType)
		{
		case Line_ZTurning_Type:
			return zTurningFeaturePoints();
		case Line_ZCenter_Type:
			return zCenterFeaturePoints();
		case Line_STurning_Type:
			return sTurningFeaturePoints();
		case Line_SCenter_Type:
			return sCenterFeaturePoints();
		case Line_OClock_Type:
			return oClockFeaturePoints();
		default:
			break;
		}
	}

	LineType CalculateFeaturePoints::getLineType() const
	{
		return _lineType;
	}

	QList<QPoint> CalculateFeaturePoints::zTurningFeaturePoints()
	{
		QList<QPoint> pts;
		pts.append(_from);
		pts.append(QPoint(_from.x() + _turningPointLength, _from.y()));
		pts.append(QPoint(_from.x() + _turningPointLength, _to.y()));
		pts.append(_to);
		return pts;
	}

	QList<QPoint> CalculateFeaturePoints::zCenterFeaturePoints()
	{
		QList<QPoint> pts;
		auto xPos = (_from.x() + _to.x()) / 2;
		pts.append(_from);
		pts.append(QPoint(xPos, _from.y()));
		pts.append(QPoint(xPos, _to.y()));
		pts.append(_to);
		return pts;
	}

	QList<QPoint> CalculateFeaturePoints::sTurningFeaturePoints()
	{
		QList<QPoint> pts;
		pts.append(_from);
		pts.append(QPoint(_from.x() + _turningPointLength, _from.y()));
		if (_from.y() > _to.y())
		{
			pts.append(QPoint(_from.x() + _turningPointLength, _from.y() - _itemTopHeight - _turningPointLength));
			pts.append(QPoint(_to.x() - _turningPointLength, _from.y() - _itemTopHeight - _turningPointLength));
		}
		else
		{
			/// need update to consider name item
			pts.append(QPoint(_from.x() + _turningPointLength, _from.y() + _itemBottomHeight + _turningPointLength));
			pts.append(QPoint(_to.x() - _turningPointLength, _from.y() + _itemBottomHeight + _turningPointLength));
		}
		pts.append(QPoint(_to.x() - _turningPointLength, _to.y()));
		pts.append(_to);
		return pts;
	}

	QList<QPoint> CalculateFeaturePoints::sCenterFeaturePoints()
	{
		QList<QPoint> pts;
		pts.append(_from);
		pts.append(QPoint(_from.x() + _turningPointLength, _from.y()));

		int distanceY = fabs(_from.y() - _to.y());

		if (_from.y() > _to.y())
		{
			int centerY = _to.y() + _itemBottomHeight + (distanceY -  _itemTopHeight - _itemBottomHeight) / 2;
			pts.append(QPoint(_from.x() + _turningPointLength, centerY));
			pts.append(QPoint(_to.x() - _turningPointLength, centerY));
		}
		else
		{
			int centerY = _from.y() + _itemBottomHeight + (distanceY - _itemTopHeight - _itemBottomHeight) / 2;
			pts.append(QPoint(_from.x() + _turningPointLength, centerY));
			pts.append(QPoint(_to.x() - _turningPointLength, centerY));
		}
		pts.append(QPoint(_to.x() - _turningPointLength, _to.y()));
		pts.append(_to);
		return pts;
	}

	QList<QPoint> CalculateFeaturePoints::oClockFeaturePoints()
	{
		QList<QPoint> pts;
		QPoint pt1, pt2, pt3, pt4;
		if (_from.y() > _to.y())
		{ 
			if (_from.y() > _to.y())
			{
				/**
				*  FromItem at ToItem 's Bottom Right . no need to consider ToItem 's right part
				*  just consider FromItem 's right part
				*/
				pt1 = QPoint(_from.x() + _turningPointLength, _from.y());
				pt2 = QPoint(pt1.x(), _from.y() + _itemBottomHeight + _turningPointLength);
				pt3 = QPoint(_to.x() - _turningPointLength, pt2.y());
				pt4 = QPoint(pt3.x(), _to.y());
			}
			else
			{
				/**
				*  FromItem at ToItem 's Bottom Left . no need to consider FromItem 's right part
				*  just consider ToItem 's right part
				*/
				pt1 = QPoint(_from.x() + _turningPointLength, _from.y());
				pt2 = QPoint(pt1.x(), _from.y() + _itemBottomHeight + _turningPointLength);
				pt3 = QPoint(_from.x() - _turningPointLength, pt2.y());
				pt4 = QPoint(pt3.x(), _to.y());
			}
		}
		else
		{
			if (_from.x() > _to.x())
			{
				/**
				*  FromItem at ToItem 's Top Right . no need to consider ToItem 's right part
				*  just consider FromItem 's right part. 
				*/
				pt1 = QPoint(_from.x() + _turningPointLength, _from.y());
				pt2 = QPoint(pt1.x(), _to.y() + _itemBottomHeight + _turningPointLength);
				pt3 = QPoint(_to.x() - _turningPointLength, pt2.y());
				pt4 = QPoint(pt3.x(), _to.y());
			}
			else
			{
				/**
				*  FromItem at ToItem 's Top Left . no need to consider FromItem 's right part
				*  just consider ToItem 's right part.
				*/
				pt1 = QPoint(_to.x() + _itemWidth + _turningPointLength, _from.y());
				pt2 = QPoint(pt1.x(), _to.y() + _itemBottomHeight + _turningPointLength);
				pt3 = QPoint(_to.x() - _turningPointLength, pt2.y());
				pt4 = QPoint(pt3.x(), _to.y());
			}
		}
		pts.append(_from);
		pts.append(pt1);
		pts.append(pt2);
		pts.append(pt3);
		pts.append(pt4);
		pts.append(_to);
		return pts;
	}
}